﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using System.Windows.Forms;
using DatabaseCore;
using Eaktest;
using SystemCore;

namespace EakTest
{
    public partial class OrderDetailInquiry : BaseForm
    {
        IOrderDao orderDao = new OrderDao();
        IOrderDetailDao orderDetailDao = new OrderDetailDao();
        //IStockProductDao stockProductDao = new StockProductDao();
        IProdQueueDao prodQueueDao = new ProdQueueDao();
        IProductQueueMappedDao productQueueMappedDao = new ProductQueueMappedDao();

        SapService.SapWebServiceSoapClient sapService = new SapService.SapWebServiceSoapClient();
        


        private tbl_Order OrderDataSource { get; set; }
        private IList<tbl_OrderDetail> OrderDetailDataSource { get; set; }

        string OrderNo = "250214000001";
        private int testStock = 10000;

        public OrderDetailInquiry() : this(string.Empty)
        {
            
        }

        public OrderDetailInquiry(string orderNo)
        {
            InitializeComponent();

            OrderNo = orderNo;

            GetOrder();
            GetOrderDetail();
            if (IsNotFound())
                return;

            BindData();

            txtOrderNo.Text = orderNo;
        }

        #region Event

        #region Override method

        public override void SaveDraft()
        {
            SaveOrder(EOrderStatus.Order);
        }

        public override void SendApprove()
        {
            SaveOrder(EOrderStatus.WaitForApprove);
        }

        #endregion

        #region Button Click

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            BindData();
        }

        private void btnCheckStock_Click(object sender, EventArgs e)
        {
            CheckStock();
        }

        #endregion

        #endregion

        #region Private method

        private void GetOrder()
        {
            OrderDataSource = orderDao.GetByKey(OrderNo);
        }

        private void GetOrderDetail()
        {
            OrderDetailDataSource = orderDetailDao.SearchByOrderNo(OrderNo);
        }

        private void ClearGridView()
        {
            gvOrderDetail.Rows.Clear();
            gvOrderDetail.DataSource = null;
        }

        private void BindData()
        {
            ClearGridView();

            int i = 0;
            foreach (var item in OrderDetailDataSource)
            {
                gvOrderDetail.Rows.Add();

                gvOrderDetail[(int)EOrderDetailCol.OrderNo, i].Value = item.OrderNo;
                gvOrderDetail[(int)EOrderDetailCol.ItemNo, i].Value = item.ItemNo;
                gvOrderDetail[(int)EOrderDetailCol.MaterialNo, i].Value = item.MaterialNo;
                gvOrderDetail[(int)EOrderDetailCol.Qty, i].Value = item.Qty;
                gvOrderDetail[(int)EOrderDetailCol.Plant, i].Value = item.Plant;
                gvOrderDetail[(int)EOrderDetailCol.Atp, i].Value = 0;
                gvOrderDetail[(int)EOrderDetailCol.CreateDate, i].Value = item.CreateDate;

                gvOrderDetail[(int)EOrderDetailCol.Qty, i].Style.ForeColor = Color.Blue;

                i++;
            }
        }

        private bool IsNotFound()
        {
            if (OrderDetailDataSource == null || OrderDetailDataSource.Count == 0)
            {
                ClearGridView();
                MessageDialog.Information("Search not found");
                return true;
            }

            return false;
        }

        private void CheckStock()
        {
            int i = 0;
            foreach (var item in OrderDetailDataSource)
            {
                //gvOrderDetail[(int)EOrderDetailCol.Plant, i].Value = item.Plant; //อ่าน Plant จาก stockProduct?
                gvOrderDetail[(int)EOrderDetailCol.Atp, i].Value = sapService.GetAtp(null, null, null); //stockProductDao.GetStockQty(item.MaterialNo);

                i++;
            }
        }

        private void SaveOrder(EOrderStatus orderStatus)
        {
            if (!MessageDialog.Confirmation("Do you want to save?"))
                return;

            /* CheckStock */
            //ไม่ต้อง Validate stock ก่อนเซฟ เพราะสามารถให้ไปอยู๋ในคิวได้
            //if (!IsAvailableStock())
            //{
            //    MessageDialog.Warning("Qty cannot more than Atp.");
            //    return;
            //}

            try
            {
                using (var ts = new TransactionScope())
                {
                    /* Saving */
                    List<tbl_OrderDetail> listOrderDetail = null;

                    /* Is qty different from db? */
                    int itemNo, newQty, oldQty, pcsPerBox, package, stockQty;
                    decimal unitPrice, amount, weightPerUnit, weight;

                    int totalNewQty = 0, totalPackage = 0;
                    decimal totalAmount = 0, totalWeight = 0;

                    for (int iRow = 0; iRow < gvOrderDetail.Rows.Count; iRow++)
                    {
                        itemNo = -1;
                        newQty = 0;

                        //ถ้ามีการเปลี่ยน qty ก็ต้องคำนวณ price, package, weight ใหม่ด้วย
                        //รวมไปถึง total ของ order ด้วย
                        //isSelect = Convert.ToBoolean(gvOrderDetail.Rows[iRow].Cells[(int) EOrderDetailCol.Sel].Value);
                        itemNo = Convert.ToInt32(gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.ItemNo].Value);
                        newQty = Convert.ToInt32(gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.Qty].Value);
                        stockQty = Convert.ToInt32(gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.Atp].Value);

                        oldQty =
                            OrderDetailDataSource.Where(c => c.ItemNo == itemNo).Select(x => x.Qty).FirstOrDefault();
                        unitPrice =
                            OrderDetailDataSource.Where(c => c.ItemNo == itemNo)
                                .Select(x => x.UnitPrice)
                                .FirstOrDefault()
                                .GetValueOrDefault();
                        pcsPerBox =
                            OrderDetailDataSource.Where(c => c.ItemNo == itemNo)
                                .Select(x => x.PcsPerBox)
                                .FirstOrDefault()
                                .GetValueOrDefault();
                        weightPerUnit =
                            OrderDetailDataSource.Where(c => c.ItemNo == itemNo)
                                .Select(x => x.WeightPerUnit)
                                .FirstOrDefault()
                                .GetValueOrDefault();

                        amount = newQty * unitPrice;
                        package = Convert.ToInt32((Math.Ceiling((decimal)newQty / pcsPerBox)));
                        weight = newQty * weightPerUnit;

                        //Sum 
                        totalNewQty += newQty;
                        totalAmount += amount;
                        totalPackage += package;
                        totalWeight += weight;

                        if (newQty == oldQty)
                            continue;

                        #region OrderDetail

                        if (listOrderDetail == null)
                            listOrderDetail = new List<tbl_OrderDetail>();

                        tbl_OrderDetail orderDetail = new tbl_OrderDetail();
                        orderDetail.OrderNo =
                            gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.OrderNo].Value.ToString();
                        orderDetail.ItemNo = itemNo;
                        orderDetail.Qty = newQty;
                        orderDetail.Amount = amount;
                        orderDetail.Package = package;
                        orderDetail.Weight = weight;
                        orderDetail.UpdateBy = UserContext.FullName;
                        orderDetail.UpdateDate = DateTime.Now;
                        orderDetail.RemainingQty = newQty;

                        listOrderDetail.Add(orderDetail);

                        #endregion

                        //Set newQty to DataSource
                        OrderDetailDataSource.Where(c => c.ItemNo == itemNo).FirstOrDefault().Qty = newQty;
                        OrderDetailDataSource.Where(c => c.ItemNo == itemNo).FirstOrDefault().RemainingQty = newQty;

                    }

                    /* Update OrderDetail */
                    if (listOrderDetail != null && listOrderDetail.Count > 0)
                    {
                        orderDetailDao.Update(listOrderDetail, string.Empty, string.Empty);
                    }

                    /* Update Order*/
                    OrderDataSource.TotalQty = totalNewQty;
                    OrderDataSource.TotalAmount = totalAmount;
                    OrderDataSource.TotalPackage = totalPackage;
                    OrderDataSource.TotalWeight = totalWeight;
                    OrderDataSource.Status = (int)orderStatus;
                    OrderDataSource.UpdateBy = UserContext.FullName;
                    OrderDataSource.UpdateDate = DateTime.Now;
                    tbl_Order order = OrderDataSource;
                    orderDao.Update(order);

                    //Approver
                    if ((int)ERole.Approver == UserContext.Role || (int)ERole.Admin == UserContext.Role)
                    {
                        //เช็คสต็อกอีกครั้ง ก่อนทำการ process
                        CheckStock();

                        // ถ้าสินค้าพอในสต็อก ก็ตัดสต็อกจาก StockProduct ได้เลย (Closed)  (StockProduct ไม่ต้องใช้แล้ว)
                        // ถ้าพอบางส่วนก็ตัดเท่าที่ได้  ที่เหลือรอในคิว ProdQueue (Queue)
                        // ถ้าไม่พอให้ไปรอในคิว ProdQueue ? (Queue)
                        string materialNo = string.Empty;
                        string orderNo = string.Empty;
                        itemNo = 0; //ประกาศไว้ข้างบนแล้ว
                        int moveQty = 0;
                        string plantCode = string.Empty;
                        int atp = 0;
                        int queueQty = 0;
                        //bool isUpdateStockSuccess = false;
                        bool isClosed = false;
                        bool isAllClosed = true;
                        for (int iRow = 0; iRow < gvOrderDetail.Rows.Count; iRow++)
                        {
                            isClosed = false;

                            materialNo = gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.MaterialNo].Value.ToString();
                            orderNo = gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.OrderNo].Value.ToString();
                            itemNo = Convert.ToInt32(gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.ItemNo].Value.ToString());
                            moveQty = Convert.ToInt32(gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.Qty].Value);
                            plantCode = gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.Plant].Value.ToString();
                            atp = Convert.ToInt32(gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.Atp].Value);

                            //process เฉพาะที่มี qty มากกว่า 0
                            if (moveQty > 0)
                            {
                                //สินค้าพอในสต็อกทั้งหมด
                                if (moveQty <= atp)
                                {
                                    //อัพเดต ReceivedQty, RemainingQty of OrderDetail
                                    orderDetailDao.UpdateReceivedQty(orderNo, itemNo, moveQty, UserContext.Username, moveQty, "test");

                                    //ตัดสต็อกได้ทั้งหมด
                                    //stockProductDao.UpdateStockQty(materialNo, moveQty);

                                    //เซฟลง ProductQueueMapped ว่าตัดสต็อกไปได้แล้ว
                                    ProductQueueMapped productQueueMapped = new ProductQueueMapped();
                                    productQueueMapped.ProductId = materialNo;
                                    productQueueMapped.PlantCode = plantCode; 
                                    productQueueMapped.OrderNo = orderNo;
                                    productQueueMapped.Qty = moveQty;
                                    //productQueueMapped.QueueID;
                                    //productQueueMapped.PalletDetailID;
                                    productQueueMappedDao.Insert(productQueueMapped);

                                    //ปิด Order Detail ได้
                                    isClosed = true;
                                }
                                else //สินค้ามีไม่พอ
                                {
                                    //ไม่มีสินค้านี้ในสต็อกเลย
                                    if (atp == 0)
                                    {
                                        //เอาเข้าคิวทั้งหมด
                                        queueQty = moveQty;
                                    }
                                    else //ตัดสต็อกได้บางส่วน  (moveQty > atp)
                                    {
                                        //ตัดสต็อกเท่าที่มีใน atp, ส่วนที่เหลือเอาเข้าคิว
                                        //stockProductDao.UpdateStockQty(materialNo, atp);

                                        //เซฟลง ProductQueueMapped ว่าเท่าที่ตัดสต็อกได้
                                        ProductQueueMapped productQueueMapped = new ProductQueueMapped();
                                        productQueueMapped.ProductId = materialNo;
                                        productQueueMapped.PlantCode = plantCode; 
                                        productQueueMapped.OrderNo = orderNo;
                                        productQueueMapped.Qty = atp;
                                        //productQueueMapped.QueueID;
                                        //productQueueMapped.PalletDetailID;
                                        productQueueMappedDao.Insert(productQueueMapped);

                                        //จำนวนที่ต้องไปเข้าคิว
                                        queueQty = moveQty - atp;
                                    }

                                    //อัพเดต ReceivedQty, RemainingQty of OrderDetail
                                    orderDetailDao.UpdateReceivedQty(orderNo, itemNo, atp, UserContext.Username, atp,"test");

                                    //ไปรอในคิว ProdQueue
                                    ProdQueue queue = new ProdQueue();
                                    queue.ProductCode = materialNo;
                                    queue.PlantCode = plantCode; 
                                    queue.OrderNo = orderNo;
                                    queue.Qty = queueQty;
                                    queue.Date = DateTime.Now;
                                    queue.IsActive = true;
                                    //queue.Priority = 0;
                                    prodQueueDao.Insert(queue);
                                }
                            }

                            isAllClosed = isAllClosed && isClosed;
                        }

                        //อัพเดต status ของ order
                        OrderDataSource.Status = isAllClosed ? (int)EOrderStatus.Closed : (int)EOrderStatus.Queue;
                        OrderDataSource.UpdateBy = UserContext.FullName;
                        OrderDataSource.UpdateDate = DateTime.Now;
                        order = OrderDataSource;
                        orderDao.Update(order);
                    }

                    ts.Complete();
                }

                MessageDialog.Information("Save completed");
            }
            catch (Exception ex)
            {
                MessageDialog.Error(ex.Message);
            }
        }

        private bool IsAvailableStock()
        {
            int newQty, atp;
            for (int iRow = 0; iRow < gvOrderDetail.Rows.Count; iRow++)
            {
                newQty = 0;
                atp = 0;

                newQty = Convert.ToInt32(gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.Qty].Value);
                atp = Convert.ToInt32(gvOrderDetail.Rows[iRow].Cells[(int)EOrderDetailCol.Atp].Value);

                if (newQty > atp)
                {
                    return false;
                }
            }

            return true;
        }

        private tbl_Order MappingOrder(EOrderStatus orderStatus)
        {
            OrderDataSource.Status = (int) orderStatus;

            OrderDataSource.UpdateBy = UserContext.FullName;
            OrderDataSource.UpdateDate = DateTime.Now;

            return OrderDataSource;
        }
        #endregion
    }
}
